/******************************************************************************/
/* File: message.h                                                            */
/******************************************************************************/

#ifndef MESSAGE_H
#define MESSAGE_H

#include "cjson.h"
#include "flowConfig.h"

//备注：所有的数据传输单位都是字节，如数据量单位为Byte，数据速率单位为Byte Per Second.

/******************************************************************************/
/*
 class RegisterRequest 
 
 RegisterRequest主要用于封装各CtrlClient注册和注销自己的UCPTrafficServer和TCPTrafficServer的信息
 主要包括内容： 
    register/unregister 
    流量服务器的协议（TCP/UDP） 
    服务器监听地址和端口号
 */
/******************************************************************************/

class RegisterRequest {
    
public:
    
    RegisterRequest() : sServIP(NULL) {
        
    }
    
    ~RegisterRequest() {
        
        if(sServIP) {
            delete sServIP;
            sServIP = NULL;
        }
    }

    cJSON* GenToJson();
    void ParseFromJson(cJSON *json);

public:
    int iToRegister; // 1 for Register, 0 for Unregister
    int iServProto; // 1 for TCP, 2 for UDP
    char *sServIP;
    int iServPort;
};

/******************************************************************************/
/*
 class FlowRequest
 
 FlowRequest主要用于记录控制中心对于某条流的配置。
 <备注：无论是TCP流还是UDP数据包，都可认为是一条流>
 * 主要的配置类型有： ADD / MOD / DEL
 ADD - 新建一条数据流 <配置信息通过pfc指出>
 MOD - 修改一条数据流的配置 <至于是那条流，则通过pfc指出，新的配置信息也在其中>
 DEL - 删除一条现有的数据流
 * 另外，pfc是核心数据区
 */
/******************************************************************************/
class FlowRequest {

public:

    FlowRequest() : pfc(NULL) {
        
    }
    
    ~FlowRequest() {
        if(pfc) {
            delete pfc;
            pfc = NULL;
        }
    }
    
    cJSON* GenToJson();
    void ParseFromJson(cJSON *json);

public:
    int iHandleType; // 1 for ADD, 2 for MOD, 3 for DEL
    FlowConfig *pfc;
};

/******************************************************************************/
/*
 class Request
 
 Request用于包含所有有用的信息。主要分为两类：
 * 从CtrlClient到CtrlServer的注册/注销流量服务器的请求信息 -- type number - 1
 * 从CtrlServer到CtrlClient的数据流配置请求 -- type number - 2
 */
/******************************************************************************/

class Request {
    
public:
    Request() : pServerReg(NULL), pFlowHandle(NULL) {
        
    }
    
    ~Request() {
        
        if(pServerReg) {
            delete pServerReg;
            pServerReg = NULL;
        }
        
        if(pFlowHandle) {
            delete pFlowHandle;
            pFlowHandle = NULL;
        }

    }

    cJSON* GenToJson();
    void ParseFromJson(cJSON *json);
    
public:
    int iRequestType; // 1 for Register/Unregister request, 2 for Flow Config request.
    
    RegisterRequest *pServerReg;
    FlowRequest *pFlowHandle;
};

/******************************************************************************/
/*
 class FlowReply
 
 FlowReply主要用于记录当成功建立新的数据流时的连接数据.
 这些数据主要包括：
 * 起始IP地址/起始端口号
 * 数据流配置信息
 */
/******************************************************************************/
class FlowReply {
public:
    FlowReply() : sSenderIP(NULL), sRecverIP(NULL) {
        
    }
    
    ~FlowReply() {
        if(sSenderIP) {
            delete sSenderIP;
            sSenderIP = NULL;
        }
        
        if(sRecverIP) {
            delete sRecverIP;
            sRecverIP = NULL;
        }
    }
    
    cJSON* GenToJson();
    void ParseFromJson(cJSON *json);
    
public:
    char *sSenderIP;
    char *sRecverIP;
    int iSenderPort;
    int iRecverPort;
    FlowConfig *pfc;
};

/******************************************************************************/
/*
 class Reply
 
 Reply并不像表面那样简单，其主要包含三类：
 
 * 从CtrlServer到CtrlClient的反馈消息
    这里又主要指的是CtrlClient发送注册和注销流量服务器的反馈请求
    注册流量服务器的反馈消息 <-> RegisterReply 1
 * 从CtrlClient到CtrlServer的数据流操作反馈消息
    反馈消息中主要是包含用于保存NEW新的数据流的源目地址信息
    命令执行成功与否的反馈消息 <-> TrafficConfReply 2
            * ADD = 成功则iSuccess置为1，同时pFlowReply内容包含连接内容
            * MOD = 成功则iSuccess置为1，pFlowReply置为NULL
            * DEL = 成功则iSuccess置为1，pFlowReply置为NULL
 * 错误反馈
    操作失败/服务器未监听/连接失败/连接中途掉线等等
 */
/******************************************************************************/

class Reply {

public:
    Reply() : pFlowReply(NULL) {
        
    }
    
    ~Reply() {
        
        if(pFlowReply) {
            delete pFlowReply;
            pFlowReply = NULL;
        }
    }

    cJSON* GenToJson();
    void ParseFromJson(cJSON *json);
    
public:
    int iReplyType; 
    int iSuccess; // 0 for wrong, 1 for correct
    FlowReply *pFlowReply;
};

/******************************************************************************/
/*
 class TcpReport
 
 对于一条TCP数据流，测量该数据流的参数，这些参数主要包括下面几部分：
 1 开始时间
 2 结束时间
 3 持续时间
 4 数据总量
 5 带宽大小
 */
/******************************************************************************/

class TcpReport {

public:
    TcpReport() {
        
    }
    
    ~TcpReport() {
        
    }

    cJSON* GenToJson();
    void ParseFromJson(cJSON *json);

public:
    double fBeginTime;
    double fEndTime;
    double fInterval;
    int64_t iTransfer;
    double fBandwidth;
};

/******************************************************************************/
/*
 class UdpReport
 
 对于一条UDP数据流，测量该数据流的参数，这些参数主要包括下面几部分：
 1 开始时间
 2 结束时间
 3 持续时间
 4 数据总量
 5 带宽大小
 6 时延抖动
 7 接收/发送总数据包数
 8 丢失数据包数
 9 丢包率
 */
/******************************************************************************/

class UdpReport {
    
public:
    UdpReport() {
        
    }
    
    ~UdpReport() {
        
    }

    cJSON* GenToJson();
    void ParseFromJson(cJSON *json);
    
public:
    double fBeginTime;
    double fEndTime;
    double fInterval;
    int64_t iTransfer;
    double fBandwidth;
    double fJitter;
    int64_t iPacketLost;
    int64_t iPacketTotal;
    double fLoss;
};

/******************************************************************************/
/*
 class Report
 
 Report主要包含两类：
 1 TCP数据流统计报告数据
 2 UDP数据流统计报告数据
 */
/******************************************************************************/
class Report {
    
public:
    Report() : iRole(1), iProto(1), pTcpReport(NULL), pUdpReport(NULL) {
                   
    }
    
    ~Report() {
        if(pTcpReport) {
            delete pTcpReport;
            pTcpReport = NULL;
        }
        
        if(pUdpReport) {
            delete pUdpReport;
            pUdpReport = NULL;
        }

        if(sSenderIP) {
            delete sSenderIP;
            sSenderIP = NULL;
        }

        if(sRecverIP) {
            delete sRecverIP;
            sRecverIP = NULL;
        }
    }

    cJSON* GenToJson();
    void ParseFromJson(cJSON *json);
    
public:
    int iRole;  // 1 for Sender, 2 for Recver
    int iProto; // 1 for TCP, 2 for UDP
    
    char *sSenderIP;
    int iSenderPort;

    char *sRecverIP;
    int iRecverPort;

    TcpReport *pTcpReport;
    UdpReport *pUdpReport;
};


/******************************************************************************/
/*
 class Message
 
 Message是所有消息的容器，根据不同的消息类型，其可放入不同的信息。
 */
/******************************************************************************/

class Message {
    
public:
    Message() : sFromIP(NULL), sToIP(NULL), pRequest(NULL),
                pReply(NULL), pReport(NULL) {
        
    }
    
    ~Message() {
        if(sFromIP) {
            delete sFromIP;
            sFromIP = NULL;
        }
            
        if(sToIP) {
            delete sToIP;
            sToIP = NULL;
        }
        
        if(pRequest) {
            delete pRequest;
            pRequest = NULL;
        }
        
        if(pReply) {
            delete pReply;
            pReply = NULL;
        }
        
        if(pReport) {
            delete pReport;
            pReport = NULL;
        }
    }
    
    cJSON* GenToJson();
    void ParseFromJson(cJSON *json);
    
public:
    char *sFromIP;
    int iFromPort;
    
    char *sToIP;
    int iToPort;
    
    int iMessageType; // 1 for Request, 2 for Reply, 3 for Report
    
    Request *pRequest;
    Reply *pReply;
    Report *pReport;
};

#endif

/******************************************************************************/
/* End File: message.h                                                        */
/******************************************************************************/